home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Tools / Development / renderlib40 / src / rnd_render.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-13  |  22.7 KB  |  1,034 lines

  1.  
  2. #include "lib_init.h"
  3. #include "lib_debug.h"
  4. #include <render/render.h>
  5. #include <proto/utility.h>
  6. #include <proto/exec.h>
  7. #include <graphics/gfx.h>
  8.  
  9. #define NUMRAND    1237        /* prime number */
  10.  
  11. static LONG getrand(LONG seed)
  12. {
  13.     ULONG lo, hi;
  14.  
  15.     lo = 16807 * (LONG) (seed & 0xffff);
  16.     hi = 16807 * (LONG) ((ULONG) seed >> 16);
  17.     lo += (hi & 0x7fff) << 16;
  18.     if (lo > 2147483647)
  19.     {
  20.         lo &= 2147483647;
  21.         ++lo;
  22.     }
  23.     lo += hi >> 15;
  24.     if (lo > 2147483647)
  25.     {
  26.         lo &= 2147483647;
  27.         ++lo;
  28.     }
  29.  
  30.     return (LONG) lo;
  31. }
  32.  
  33. /************************************************************************** 
  34. **
  35. **    callbacks for rendering
  36. **
  37. **************************************************************************/
  38.  
  39. /* 
  40. **    floyd:            P    A=7
  41. **                B=3    C=5    D=1
  42. */
  43.  
  44. static __inline UBYTE dither_floyd(struct RenderData *rnd, WORD *dithbuf, WORD r, WORD g, WORD b)
  45. {
  46.     ULONG rgb;
  47.     UBYTE pen;
  48.     WORD A, B;
  49.  
  50.     r += rnd->Ar;
  51.     g += rnd->Ag;
  52.     b += rnd->Ab;
  53.  
  54.     if (r < 0) r = 0; else if (r > 255) r = 255;
  55.     if (g < 0) g = 0; else if (g > 255) g = 255;
  56.     if (b < 0) b = 0; else if (b > 255) b = 255;
  57.  
  58.     pen = P2Lookup2(rnd->dstpal, r, g, b);
  59.     rgb = rnd->dstpal->table[pen];                    
  60.  
  61.     b -= rgb & 0xff;                            
  62.     rgb >>= 8;                                    
  63.     g -= rgb & 0xff;                            
  64.     rgb >>= 8;                                    
  65.     r -= rgb & 0xff;
  66.  
  67.     B = r + r;
  68.     A = (B + r) >> 4;                        
  69.     dithbuf[0] = rnd->Br + A;
  70.     B = (B + B + r) >> 4;
  71.     A += B;
  72.     rnd->Br = rnd->Cr + B;
  73.     B = r >> 4;
  74.     rnd->Cr = B;
  75.     rnd->Ar = r - A - B;
  76.  
  77.     B = g + g;
  78.     A = (B + g) >> 4;
  79.     dithbuf[1] = rnd->Bg + A;
  80.     B = (B + B + g) >> 4;
  81.     A += B;
  82.     rnd->Bg = rnd->Cg + B;
  83.     B = g >> 4;
  84.     rnd->Cg = B;
  85.     rnd->Ag = g - A - B;
  86.  
  87.     B = b + b;
  88.     A = (B + b) >> 4;
  89.     dithbuf[2] = rnd->Bb + A;
  90.     B = (B + B + b) >> 4;
  91.     A += B;
  92.     rnd->Bb = rnd->Cb + B;
  93.     B = b >> 4;
  94.     rnd->Cb = B;
  95.     rnd->Ab = b - A - B;
  96.  
  97.     return pen;
  98. }
  99.  
  100. /************************************************************************** 
  101. **    renderx: rgb dither floyd
  102. */
  103.  
  104. static void renderx_rgb_dither_floyd(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  105. {
  106.     WORD *dithbuf = rnd->ditherbuf + 3;
  107.     ULONG rgb;
  108.     WORD r, g, b;
  109.     
  110.     rnd->Br = 0;
  111.     rnd->Cr = 0;
  112.     rnd->Ar = 0;
  113.     rnd->Bg = 0;
  114.     rnd->Cg = 0;
  115.     rnd->Ag = 0;
  116.     rnd->Bb = 0;
  117.     rnd->Cb = 0;
  118.     rnd->Ab = 0;
  119.  
  120.     if (rnd->flipflop ^= 1)
  121.     {
  122.         while (width--)
  123.         {
  124.             rgb = *src++;
  125.             r = *dithbuf++ + ((rgb & 0xff0000) >> 16);
  126.             g = *dithbuf++ + ((rgb & 0x00ff00) >> 8);
  127.             b = *dithbuf++ + (rgb & 0x0000ff);
  128.             *dst++ = rnd->pentab[dither_floyd(rnd, dithbuf - 3, r, g, b)];
  129.         }
  130.     }
  131.     else
  132.     {
  133.         src += width;
  134.         dst += width;
  135.         dithbuf += width * 3;
  136.         while (width--)
  137.         {
  138.             rgb = *--src;
  139.             b = *--dithbuf + (rgb & 0x0000ff);
  140.             g = *--dithbuf + ((rgb & 0x00ff00) >> 8);
  141.             r = *--dithbuf + ((rgb & 0xff0000) >> 16);
  142.             *--dst = rnd->pentab[dither_floyd(rnd, dithbuf + 3, r, g, b)];
  143.         }
  144.     }
  145. }
  146.  
  147.  
  148. /************************************************************************** 
  149. **    renderx: chunky dither floyd
  150. */
  151.  
  152. static void renderx_chunky_dither_floyd(struct RenderData *rnd, UBYTE *src, UBYTE *dst, LONG width)
  153. {
  154.     RNDPAL *srcpal = rnd->srcpal;
  155.     WORD *dithbuf = rnd->ditherbuf + 3;
  156.     ULONG rgb;
  157.     WORD r, g, b;
  158.     
  159.     rnd->Br = 0;
  160.     rnd->Cr = 0;
  161.     rnd->Ar = 0;
  162.     rnd->Bg = 0;
  163.     rnd->Cg = 0;
  164.     rnd->Ag = 0;
  165.     rnd->Bb = 0;
  166.     rnd->Cb = 0;
  167.     rnd->Ab = 0;
  168.  
  169.     if (rnd->flipflop ^= 1)
  170.     {
  171.         while (width--)
  172.         {
  173.             rgb = srcpal->table[*src++];
  174.             r = *dithbuf++ + ((rgb & 0xff0000) >> 16);
  175.             g = *dithbuf++ + ((rgb & 0x00ff00) >> 8);
  176.             b = *dithbuf++ + (rgb & 0x0000ff);
  177.             *dst++ = rnd->pentab[dither_floyd(rnd, dithbuf - 3, r, g, b)];
  178.         }
  179.     }
  180.     else
  181.     {
  182.         src += width;
  183.         dst += width;
  184.         dithbuf += width * 3;
  185.         while (width--)
  186.         {
  187.             rgb = srcpal->table[*--src];
  188.             b = *--dithbuf + (rgb & 0x0000ff);
  189.             g = *--dithbuf + ((rgb & 0x00ff00) >> 8);
  190.             r = *--dithbuf + ((rgb & 0xff0000) >> 16);
  191.             *--dst = rnd->pentab[dither_floyd(rnd, dithbuf + 3, r, g, b)];
  192.         }
  193.     }
  194. }
  195.  
  196.  
  197. /* 
  198. **    edd:            P    A=1
  199. **                    B=1
  200. */
  201.  
  202. #define dither_edd(rgb)                                            \
  203.     r += dithbuf[0];                                            \
  204.     g += dithbuf[1];                                            \
  205.     b += dithbuf[2];                                            \
  206.     b += rgb & 0xff;                                            \
  207.     rgb >>= 8;                                                    \
  208.     g += rgb & 0xff;                                            \
  209.     rgb >>= 8;                                                    \
  210.     r += rgb & 0xff;                                            \
  211.     if (r < 0) r = 0; else if (r > 255) r = 255;                \
  212.     if (g < 0) g = 0; else if (g > 255) g = 255;                \
  213.     if (b < 0) b = 0; else if (b > 255) b = 255;                \
  214.     rgb = r;                                                    \
  215.     rgb <<= 8;                                                    \
  216.     rgb |= g;                                                    \
  217.     rgb <<= 8;                                                    \
  218.     rgb |= b;                                                    \
  219.     pen = P2Lookup(dstpal, rgb);                                \
  220.     rgb = dstpal->table[pen];                                    \
  221.     r -= (rgb & 0xff0000) >> 16;                                \
  222.     g -= (rgb & 0x00ff00) >> 8;                                    \
  223.     b -= (rgb & 0x0000ff);                                        \
  224.     r -= dithbuf[0] = r >> 1;                                    \
  225.     g -= dithbuf[1] = g >> 1;                                    \
  226.     b -= dithbuf[2] = b >> 1;
  227.  
  228.  
  229. /************************************************************************** 
  230. **    renderx: rgb dither EDD
  231. */
  232.  
  233. static void renderx_rgb_dither_edd(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  234. {
  235.     UBYTE *pentab = rnd->pentab;
  236.     RNDPAL *dstpal = rnd->dstpal;
  237.     WORD *dithbuf = rnd->ditherbuf;
  238.     ULONG rgb;
  239.     WORD r = 0, g = 0, b = 0;
  240.     UBYTE pen;
  241.  
  242.     if (rnd->flipflop ^= 1)
  243.     {    
  244.         while (width--)
  245.         {
  246.             rgb = *src++;
  247.             dither_edd(rgb);
  248.             *dst++ = pentab[pen];
  249.             dithbuf += 3;
  250.         }
  251.     }
  252.     else
  253.     {
  254.         src += width;
  255.         dst += width;
  256.         dithbuf += width * 3;
  257.         while (width--)
  258.         {
  259.             dithbuf -= 3;
  260.             rgb = *--src;
  261.             dither_edd(rgb);
  262.             *--dst = pentab[pen];
  263.         }
  264.     }
  265. }
  266.  
  267.  
  268. /************************************************************************** 
  269. **    renderx: chunky dither EDD
  270. */
  271.  
  272. static void renderx_chunky_dither_edd(struct RenderData *rnd, UBYTE *src, UBYTE *dst, LONG width)
  273. {
  274.     UBYTE *pentab = rnd->pentab;
  275.     RNDPAL *srcpal = rnd->srcpal;
  276.     RNDPAL *dstpal = rnd->dstpal;
  277.     WORD *dithbuf = rnd->ditherbuf;
  278.     ULONG rgb;
  279.     WORD r = 0, g = 0, b = 0;
  280.     UBYTE pen;
  281.  
  282.     if (rnd->flipflop ^= 1)
  283.     {    
  284.         while (width--)
  285.         {
  286.             rgb = srcpal->table[*src++];
  287.             dither_edd(rgb);
  288.             *dst++ = pentab[pen];
  289.             dithbuf += 3;
  290.         }
  291.     }
  292.     else
  293.     {
  294.         src += width;
  295.         dst += width;
  296.         dithbuf += width * 3;
  297.         while (width--)
  298.         {
  299.             dithbuf -= 3;
  300.             rgb = srcpal->table[*--src];
  301.             dither_edd(rgb);
  302.             *--dst = pentab[pen];
  303.         }
  304.     }
  305. }
  306.  
  307.  
  308.  
  309. /* 
  310. **    random dither
  311. */
  312.  
  313. #define dither_random(rgb)                                        \
  314.     b += rgb & 0xff;                                            \
  315.     rgb >>= 8;                                                    \
  316.     g += rgb & 0xff;                                            \
  317.     rgb >>= 8;                                                    \
  318.     r += rgb & 0xff;                                            \
  319.     if (r < 0) r = 0; else if (r > 255) r = 255;                \
  320.     if (g < 0) g = 0; else if (g > 255) g = 255;                \
  321.     if (b < 0) b = 0; else if (b > 255) b = 255;                \
  322.     rgb = r;                                                    \
  323.     rgb <<= 8;                                                    \
  324.     rgb |= g;                                                    \
  325.     rgb <<= 8;                                                    \
  326.     rgb |= b;                                                    \
  327.     pen = P2Lookup(dstpal, rgb);                                \
  328.     rgb = dstpal->table[pen];                                    \
  329.     b -= rgb & 0xff;                                            \
  330.     rgb >>= 8;                                                    \
  331.     g -= rgb & 0xff;                                            \
  332.     rgb >>= 8;                                                    \
  333.     r -= rgb & 0xff;                                            \
  334.     if (--randi < 0) randi = NUMRAND - 1;                        \
  335.     r += rnd->randtab[randi];                                    \
  336.     if (--randi < 0) randi = NUMRAND - 1;                        \
  337.     g += rnd->randtab[randi];                                    \
  338.     if (--randi < 0) randi = NUMRAND - 1;                        \
  339.     b += rnd->randtab[randi];
  340.  
  341.  
  342. /************************************************************************** 
  343. **    renderx: rgb dither random
  344. */
  345.  
  346. static void renderx_rgb_dither_rand(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  347. {
  348.     UBYTE *pentab = rnd->pentab;
  349.     RNDPAL *dstpal = rnd->dstpal;
  350.     WORD *dithbuf = rnd->ditherbuf;
  351.     ULONG rgb;
  352.     WORD r = 0, g = 0, b = 0;
  353.     UBYTE pen;
  354.     WORD randi = rnd->randi;
  355.  
  356.     if (rnd->flipflop ^= 1)
  357.     {    
  358.         while (width--)
  359.         {
  360.             rgb = *src++;
  361.             dither_random(rgb);
  362.             *dst++ = pentab[pen];
  363.             dithbuf += 3;
  364.         }
  365.     }
  366.     else
  367.     {
  368.         src += width;
  369.         dst += width;
  370.         dithbuf += width * 3;
  371.         while (width--)
  372.         {
  373.             dithbuf -= 3;
  374.             rgb = *--src;
  375.             dither_random(rgb);
  376.             *--dst = pentab[pen];
  377.         }
  378.     }
  379.     
  380.     rnd->randi = randi;
  381. }
  382.  
  383.  
  384. /************************************************************************** 
  385. **    renderx: chunky dither random
  386. */
  387.  
  388. static void renderx_chunky_dither_rand(struct RenderData *rnd, UBYTE *src, UBYTE *dst, LONG width)
  389. {
  390.     UBYTE *pentab = rnd->pentab;
  391.     RNDPAL *srcpal = rnd->srcpal;
  392.     RNDPAL *dstpal = rnd->dstpal;
  393.     WORD *dithbuf = rnd->ditherbuf;
  394.     ULONG rgb;
  395.     WORD r = 0, g = 0, b = 0;
  396.     UBYTE pen;
  397.     WORD randi = rnd->randi;
  398.  
  399.     if (rnd->flipflop ^= 1)
  400.     {    
  401.         while (width--)
  402.         {
  403.             rgb = srcpal->table[*src++];
  404.             dither_random(rgb);
  405.             *dst++ = pentab[pen];
  406.             dithbuf += 3;
  407.         }
  408.     }
  409.     else
  410.     {
  411.         src += width;
  412.         dst += width;
  413.         dithbuf += width * 3;
  414.         while (width--)
  415.         {
  416.             dithbuf -= 3;
  417.             rgb = srcpal->table[*--src];
  418.             dither_random(rgb);
  419.             *--dst = pentab[pen];
  420.         }
  421.     }
  422.  
  423.     rnd->randi = randi;
  424. }
  425.  
  426.  
  427.  
  428.  
  429. /************************************************************************** 
  430. **    renderx: rgb plain
  431. */
  432.  
  433. static void renderx_rgb_plain(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  434. {
  435.     RNDPAL *dstpal = rnd->dstpal;
  436.     while (width--)
  437.     {
  438.         *dst++ = P2Lookup(dstpal, *src++);
  439.     }
  440. }
  441.  
  442. /************************************************************************** 
  443. **    renderx: rgb with pentab
  444. */
  445.  
  446. static void renderx_rgb_pentab(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  447. {
  448.     UBYTE *pentab = rnd->pentab;
  449.     RNDPAL *dstpal = rnd->dstpal;
  450.     while (width--)
  451.     {
  452.         *dst++ = pentab[P2Lookup(dstpal, *src++)];
  453.     }
  454. }
  455.  
  456.  
  457.  
  458. #define lookupham6(rgb,r,g,b)                            \
  459. {    LONG nr, ng, nb, d, bestd; ULONG rgb2; UBYTE p2;    \
  460.     nr = (rgb & 0xf00000) >> 20;                        \
  461.     ng = (rgb & 0x00f000) >> 12;                    \
  462.     nb = (rgb & 0x0000f0) >> 4;                        \
  463.     bestd = (ng-g)*(ng-g) + (nb-b)*(nb-b);            \
  464.     pen = 0x20 | nr;                                \
  465.     rgb2 = (nr << 8) | (g << 4) | b;                \
  466.     d = (nr-r)*(nr-r) + (nb-b)*(nb-b);                \
  467.     if (d < bestd)                                    \
  468.     {                                                \
  469.         bestd = d;                                    \
  470.         pen = 0x30 | ng;                            \
  471.         rgb2 = (r << 8) | (ng << 4) | b;            \
  472.     }                                                \
  473.     d = (nr-r)*(nr-r) + (ng-g)*(ng-g);                \
  474.     if (d < bestd)                                    \
  475.     {                                                \
  476.         bestd = d;                                    \
  477.         pen = 0x10 | nb;                            \
  478.         rgb2 = (r << 8) | (g << 4) | nb;            \
  479.     }                                                \
  480.     p2 = P2Lookup(dstpal, rgb);                        \
  481.     rgb = dstpal->table[p2];                        \
  482.     r = (rgb & 0xf00000) >> 20;                        \
  483.     g = (rgb & 0x00f000) >> 12;                        \
  484.     b = (rgb & 0x0000f0) >> 4;                        \
  485.     nr -= r;                                        \
  486.     ng -= g;                                        \
  487.     nb -= b;                                        \
  488.     if (nr*nr + ng*ng + nb*nb < bestd)                \
  489.     {                                                \
  490.         pen = pentab[p2];                            \
  491.     }                                                \
  492.     else                                            \
  493.     {                                                \
  494.         r = (rgb2 & 0xf00) >> 8;                    \
  495.         g = (rgb2 & 0x0f0) >> 4;                    \
  496.         b = (rgb2 & 0x00f);                            \
  497.     }                                                \
  498. }
  499.  
  500. /************************************************************************** 
  501. **    renderx: rgb to ham6
  502. */
  503.  
  504. static void renderx_rgb_ham6(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  505. {
  506.     UBYTE *pentab = rnd->pentab;
  507.     RNDPAL *dstpal = rnd->dstpal;
  508.  
  509.     LONG hr = (dstpal->table[0] & 0xf00000) >> 20;
  510.     LONG hg = (dstpal->table[0] & 0x00f000) >> 12;
  511.     LONG hb = (dstpal->table[0] & 0x0000f0) >> 4;
  512.     ULONG rgb;
  513.     UBYTE pen;
  514.     
  515.     while (width--)
  516.     {
  517.         rgb = *src++;
  518.         lookupham6(rgb, hr,hg,hb);
  519.         *dst++ = pen;
  520.     }
  521. }
  522.  
  523. /************************************************************************** 
  524. **    renderx: chunky to ham6
  525. */
  526.  
  527. static void renderx_chunky_ham6(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  528. {
  529.     UBYTE *pentab = rnd->pentab;
  530.     RNDPAL *srcpal = rnd->srcpal;
  531.     RNDPAL *dstpal = rnd->dstpal;
  532.  
  533.     LONG hr = (dstpal->table[0] & 0xf00000) >> 20;
  534.     LONG hg = (dstpal->table[0] & 0x00f000) >> 12;
  535.     LONG hb = (dstpal->table[0] & 0x0000f0) >> 4;
  536.     ULONG rgb;
  537.     UBYTE pen;
  538.     
  539.     while (width--)
  540.     {
  541.         rgb = srcpal->table[*src++];
  542.         lookupham6(rgb, hr,hg,hb);
  543.         *dst++ = pen;
  544.     }
  545. }
  546.  
  547.  
  548.  
  549.  
  550. #define lookupham8(rgb,r,g,b)                            \
  551. {    LONG nr, ng, nb, d, bestd; ULONG rgb2; UBYTE p2;    \
  552.     nr = (r & 3) | ((rgb & 0xfc0000) >> 16);            \
  553.     ng = (g & 3) | ((rgb & 0x00fc00) >> 8);            \
  554.     nb = (b & 3) | (rgb & 0x0000fc);                \
  555.     bestd = (ng-g)*(ng-g) + (nb-b)*(nb-b);            \
  556.     pen = 0x80 | (nr>>2);                            \
  557.     rgb2 = (nr << 16) | (g << 8) | b;                \
  558.     d = (nr-r)*(nr-r) + (nb-b)*(nb-b);                \
  559.     if (d < bestd)                                    \
  560.     {                                                \
  561.         bestd = d;                                    \
  562.         pen = 0xc0 | (ng>>2);                        \
  563.         rgb2 = (r << 16) | (ng << 8) | b;            \
  564.     }                                                \
  565.     d = (nr-r)*(nr-r) + (ng-g)*(ng-g);                \
  566.     if (d < bestd)                                    \
  567.     {                                                \
  568.         bestd = d;                                    \
  569.         pen = 0x40 | (nb>>2);                        \
  570.         rgb2 = (r << 16) | (g << 8) | nb;            \
  571.     }                                                \
  572.     p2 = P2Lookup(dstpal, rgb);                        \
  573.     rgb = dstpal->table[p2];                        \
  574.     r = (rgb & 0xff0000) >> 16;                        \
  575.     g = (rgb & 0x00ff00) >> 8;                        \
  576.     b = (rgb & 0x0000ff);                            \
  577.     nr -= r;                                        \
  578.     ng -= g;                                        \
  579.     nb -= b;                                        \
  580.     if (nr*nr + ng*ng + nb*nb < bestd)                \
  581.     {                                                \
  582.         pen = pentab[p2];                            \
  583.     }                                                \
  584.     else                                            \
  585.     {                                                \
  586.         r = (rgb2 & 0xff0000) >> 16;                \
  587.         g = (rgb2 & 0x00ff00) >> 8;                    \
  588.         b = (rgb2 & 0x0000ff);                        \
  589.     }                                                \
  590. }
  591.  
  592. /************************************************************************** 
  593. **    renderx: rgb to ham8
  594. */
  595.  
  596. static void renderx_rgb_ham8(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  597. {
  598.     UBYTE *pentab = rnd->pentab;
  599.     RNDPAL *dstpal = rnd->dstpal;
  600.  
  601.     LONG hr = (dstpal->table[0] & 0xff0000) >> 16;
  602.     LONG hg = (dstpal->table[0] & 0x00ff00) >> 8;
  603.     LONG hb = (dstpal->table[0] & 0x0000ff);
  604.     ULONG rgb;
  605.     UBYTE pen;
  606.     
  607.     while (width--)
  608.     {
  609.         rgb = *src++;
  610.         lookupham8(rgb, hr,hg,hb);
  611.         *dst++ = pen;
  612.     }
  613. }
  614.  
  615. /************************************************************************** 
  616. **    renderx: chunky to ham8
  617. */
  618.  
  619. static void renderx_chunky_ham8(struct RenderData *rnd, ULONG *src, UBYTE *dst, LONG width)
  620. {
  621.     UBYTE *pentab = rnd->pentab;
  622.     RNDPAL *srcpal = rnd->srcpal;
  623.     RNDPAL *dstpal = rnd->dstpal;
  624.  
  625.     LONG hr = (dstpal->table[0] & 0xff0000) >> 16;
  626.     LONG hg = (dstpal->table[0] & 0x00ff00) >> 8;
  627.     LONG hb = (dstpal->table[0] & 0x0000ff);
  628.     ULONG rgb;
  629.     UBYTE pen;
  630.     
  631.     while (width--)
  632.     {
  633.         rgb = srcpal->table[*src++];
  634.         lookupham8(rgb, hr,hg,hb);
  635.         *dst++ = pen;
  636.     }
  637. }
  638.  
  639.  
  640.  
  641.  
  642. /************************************************************************** 
  643. **    renderx: chunky plain
  644. */
  645.  
  646. static void renderx_chunky_plain(struct RenderData *rnd, UBYTE *src, UBYTE *dst, LONG width)
  647. {
  648.     RNDPAL *srcpal = rnd->srcpal;
  649.     RNDPAL *dstpal = rnd->dstpal;
  650.     while (width--)
  651.     {
  652.         *dst++ = P2Lookup(dstpal, srcpal->table[*src++]);
  653.     }
  654. }
  655.  
  656. /************************************************************************** 
  657. **    renderx: chunky with pentab
  658. */
  659.  
  660. static void renderx_chunky_pentab(struct RenderData *rnd, UBYTE *src, UBYTE *dst, LONG width)
  661. {
  662.     RNDPAL *srcpal = rnd->srcpal;
  663.     RNDPAL *dstpal = rnd->dstpal;
  664.     UBYTE *pentab = rnd->pentab;
  665.     while (width--)
  666.     {
  667.         *dst++ = pentab[P2Lookup(dstpal, srcpal->table[*src++])];
  668.     }
  669. }
  670.  
  671.  
  672.  
  673.  
  674. /************************************************************************** 
  675. **    rendery: plain with hooks
  676. */
  677.  
  678. static ULONG rendery_plain_hooks(struct RenderData *rnd)
  679. {
  680.     ULONG result = REND_CALLBACK_ABORTED;
  681.     UBYTE *src = rnd->src;
  682.     UBYTE *dst = rnd->dst;
  683.     LONG y;
  684.  
  685.     for (y = 0; y < rnd->height; ++y)
  686.     {
  687.         if (rnd->linehook)
  688.         {
  689.             rnd->fetchmsg.RND_LMsg_row = y;
  690.             if (!CallHookPkt(rnd->linehook, src, &rnd->fetchmsg)) goto abort;
  691.         }
  692.  
  693.         (*rnd->renderxfunc)(rnd, src, dst, rnd->width);
  694.  
  695.         if (rnd->linehook)
  696.         {
  697.             rnd->rendermsg.RND_LMsg_row = y;
  698.             if (!CallHookPkt(rnd->linehook, dst, &rnd->rendermsg)) goto abort;
  699.         }
  700.  
  701.         if (rnd->proghook)
  702.         {
  703.             rnd->progmsg.RND_PMsg_count = y;
  704.             if (!CallHookPkt(rnd->proghook, rnd->dstpal, &rnd->progmsg)) goto abort;
  705.         }
  706.  
  707.         src += rnd->tsw * rnd->srcbpp;
  708.         dst += rnd->tdw * rnd->dstbpp;
  709.     }
  710.  
  711.     result = REND_SUCCESS;
  712.  
  713. abort:
  714.     return result;
  715. }
  716.  
  717.  
  718. /************************************************************************** 
  719. **    rendery: with scale-engine and hooks
  720. */
  721.  
  722. static ULONG rendery_scale_hooks(struct RenderData *rnd)
  723. {
  724.     ULONG result = REND_NOT_ENOUGH_MEMORY;
  725.     APTR linebuf;
  726.  
  727.     linebuf = AllocRenderMem(rnd->rmh, rnd->scaleengine->dw * rnd->srcbpp);
  728.     if (linebuf)
  729.     {
  730.         if ((*rnd->scaleengine->initfunc)(rnd->scaleengine, &rnd->scdata))
  731.         {
  732.             UBYTE *dst = rnd->dst;
  733.             LONG y;
  734.  
  735.             result = REND_CALLBACK_ABORTED;
  736.  
  737.             for (y = 0; y < rnd->scaleengine->dh; ++y)
  738.             {
  739.                 UBYTE *src = rnd->src;
  740.  
  741.                 if (rnd->bgcolor != 0xffffffff)
  742.                 {
  743.                     memfill32(linebuf, rnd->scaleengine->dw * rnd->srcbpp, rnd->bgcolor);
  744.                 }
  745.                 else if (rnd->bgpen != 0xffffffff)
  746.                 {
  747.                     memfill8(linebuf, rnd->scaleengine->dw * rnd->srcbpp, rnd->bgpen);
  748.                 }
  749.                 
  750.                 (*rnd->scaleengine->scalefunc)(rnd->scaleengine, &rnd->scdata, src, linebuf, y, rnd->tsw);
  751.                 (*rnd->renderxfunc)(rnd, linebuf, dst, rnd->scaleengine->dw);
  752.  
  753.                 if (rnd->linehook)
  754.                 {
  755.                     rnd->rendermsg.RND_LMsg_row = y;
  756.                     if (!CallHookPkt(rnd->linehook, dst, &rnd->rendermsg)) goto abort;
  757.                 }
  758.                 
  759.                 if (rnd->proghook)
  760.                 {
  761.                     rnd->progmsg.RND_PMsg_count = y;
  762.                     if (!CallHookPkt(rnd->proghook, rnd->dstpal, &rnd->progmsg)) goto abort;
  763.                 }
  764.  
  765.                 dst += rnd->tdw * rnd->dstbpp;
  766.             }
  767.  
  768.             result = REND_SUCCESS;
  769. abort:
  770.             (*rnd->scaleengine->exitfunc)(rnd->scaleengine, &rnd->scdata);
  771.         }
  772.         FreeRenderMem(rnd->rmh, linebuf, rnd->scaleengine->dw * rnd->srcbpp);
  773.     }
  774.     
  775.     return result;
  776. }
  777.  
  778.  
  779.  
  780. /************************************************************************** 
  781. **    init render data.
  782. **    dstpal, width, height, src, dst, srcpal, srcbpp
  783. **    must be initialized by the caller.
  784. */
  785.  
  786. static ULONG initrender(struct RenderData *rnd, struct TagItem *tags)
  787. {
  788.     LONG colormode = GetTagData(RND_ColorMode, COLORMODE_CLUT, tags);
  789.  
  790.     if (!rnd->dstpal) return REND_NO_DATA;
  791.     if (!GetP2Table(rnd->dstpal)) return REND_NOT_ENOUGH_MEMORY;
  792.  
  793.     rnd->rmh = rnd->dstpal->rmh;
  794.     rnd->dstbpp = 1;
  795.  
  796.     rnd->tsw = GetTagData(RND_SourceWidth, rnd->width, tags);
  797.     rnd->tdw = GetTagData(RND_DestWidth, rnd->width, tags);
  798.  
  799.     rnd->pentab = (UBYTE *) GetTagData(RND_PenTable, NULL, tags);
  800.     if (!rnd->pentab)
  801.     {
  802.         LONG oz = GetTagData(RND_OffsetColorZero, 0, tags);
  803.  
  804.         LONG i;
  805.         for (i = 0; i < 256; ++i)
  806.         {
  807.             rnd->pens[i] = i + oz;
  808.         }
  809.  
  810.         if (oz)
  811.         {
  812.             rnd->pentab = rnd->pens;
  813.         }
  814.     }
  815.  
  816.     rnd->proghook = (struct Hook *) GetTagData(RND_ProgressHook, NULL, tags);
  817.     rnd->linehook = (struct Hook *) GetTagData(RND_LineHook, NULL, tags);
  818.     
  819.     rnd->fetchmsg.RND_LMsg_type = LMSGTYPE_LINE_FETCH;
  820.     rnd->rendermsg.RND_LMsg_type = LMSGTYPE_LINE_RENDERED;
  821.     rnd->progmsg.RND_PMsg_type = PMSGTYPE_LINES_RENDERED;
  822.     rnd->progmsg.RND_PMsg_total = rnd->height;
  823.  
  824.     rnd->scaleengine = (struct ScaleEngine *) GetTagData(RND_ScaleEngine, NULL, tags);
  825.     if (rnd->scaleengine)
  826.     {
  827.         /* override */
  828.         rnd->width = rnd->scaleengine->dw;
  829.         rnd->height = rnd->scaleengine->dh;
  830.         
  831.         rnd->bgcolor = GetTagData(RND_BGColor, 0xffffffff, tags);
  832.         rnd->bgpen = GetTagData(RND_BGPen, 0xffffffff, tags);
  833.     }
  834.  
  835.  
  836.     rnd->dithermode = GetTagData(RND_DitherMode, DITHERMODE_NONE, tags);
  837.     if (rnd->dithermode != DITHERMODE_NONE)
  838.     {
  839.         rnd->ditherbuf = AllocRenderVecClear(rnd->rmh, sizeof(UWORD) * 3 * (rnd->width + 2));
  840.         if (!rnd->ditherbuf) return REND_NOT_ENOUGH_MEMORY;
  841.         if (rnd->dithermode == DITHERMODE_RANDOM)
  842.         {
  843.             LONG i, seed;
  844.             LONG amount = GetTagData(RND_DitherAmount, 128, tags);
  845.             rnd->randtab = AllocRenderMem(rnd->rmh, NUMRAND);
  846.             if (!rnd->randtab) return REND_NOT_ENOUGH_MEMORY;
  847.             for (i = 0; i < NUMRAND; ++i)
  848.             {
  849.                 rnd->randtab[i] = (seed = getrand(seed)) % amount - amount/2;
  850.             }
  851.         }
  852.     }
  853.     
  854.  
  855.     /* determine renderx function */
  856.     if (rnd->srcbpp == 1)
  857.     {
  858.         switch (colormode)
  859.         {
  860.             case COLORMODE_CLUT:
  861.                 switch (rnd->dithermode)
  862.                 {
  863.                     case DITHERMODE_EDD:
  864.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_dither_edd;
  865.                         break;
  866.                     case DITHERMODE_FS:
  867.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_dither_floyd;
  868.                         break;
  869.                     case DITHERMODE_RANDOM:
  870.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_dither_rand;
  871.                         break;
  872.  
  873.                     default:
  874.                     case DITHERMODE_NONE:
  875.                         if (rnd->pentab)
  876.                         {
  877.                             rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_pentab;
  878.                         }
  879.                         else
  880.                         {
  881.                             rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_plain;
  882.                         }
  883.                         break;
  884.                 }
  885.                 break;
  886.             
  887.             case COLORMODE_HAM6:
  888.                 rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_ham6;
  889.                 break;
  890.  
  891.             case COLORMODE_HAM8:
  892.                 rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_chunky_ham8;
  893.                 break;
  894.         }
  895.     }
  896.     else if (rnd->srcbpp == 4)
  897.     {
  898.         switch (colormode)
  899.         {
  900.             case COLORMODE_CLUT:
  901.                 switch (rnd->dithermode)
  902.                 {
  903.                     case DITHERMODE_EDD:
  904.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_dither_edd;
  905.                         break;
  906.                     case DITHERMODE_FS:
  907.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_dither_floyd;
  908.                         break;
  909.                     case DITHERMODE_RANDOM:
  910.                         rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_dither_rand;
  911.                         break;
  912.  
  913.                     default:
  914.                     case DITHERMODE_NONE:
  915.                         if (rnd->pentab)
  916.                         {
  917.                             rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_pentab;
  918.                         }
  919.                         else
  920.                         {
  921.                             rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_plain;
  922.                         }
  923.                         break;
  924.                 }
  925.                 break;
  926.             
  927.             case COLORMODE_HAM6:
  928.                 rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_ham6;
  929.                 break;
  930.             
  931.             case COLORMODE_HAM8:
  932.                 rnd->renderxfunc = (void (*)(struct RenderData *, APTR, APTR, LONG)) renderx_rgb_ham8;
  933.                 break;
  934.         }
  935.     }
  936.     
  937.     /* determine rendery function */
  938.     if (rnd->scaleengine)
  939.     {
  940.         rnd->renderyfunc = (ULONG (*)(struct RenderData *data)) rendery_scale_hooks;
  941.     }
  942.     else
  943.     {
  944.         rnd->renderyfunc = (ULONG (*)(struct RenderData *data)) rendery_plain_hooks;
  945.     }
  946.  
  947.  
  948.     if (!rnd->pentab) rnd->pentab = rnd->pens;
  949.  
  950.     return REND_SUCCESS;
  951. }
  952.  
  953.  
  954. static void exitrender(struct RenderData *data)
  955. {
  956.     if (data->randtab) FreeRenderMem(data->rmh, data->randtab, NUMRAND);
  957.     FreeRenderVec((ULONG *) data->ditherbuf);
  958. }
  959.  
  960.  
  961. /************************************************************************** 
  962. **
  963. **    render
  964. */
  965.  
  966. LIBAPI ULONG RenderA(ULONG *src, UWORD w, UWORD h, UBYTE *dst, RNDPAL *dstpal, struct TagItem *tags)
  967. {
  968.     ULONG result = REND_NO_DATA;
  969.  
  970.     if (src && dst && w && h && dstpal)
  971.     {
  972.         struct RenderData data;
  973.         memfill8((UBYTE *) &data, sizeof(struct RenderData), 0);
  974.         
  975.         ObtainSemaphore(&dstpal->lock);
  976.  
  977.         data.src = src;
  978.         data.srcbpp = 4;
  979.         data.dst = dst;
  980.         data.width = w;        
  981.         data.height = h;
  982.         data.dstpal = dstpal;
  983.         result = initrender(&data, tags);
  984.         if (result == REND_SUCCESS)
  985.         {
  986.             result = (*data.renderyfunc)(&data);
  987.         }
  988.         exitrender(&data);
  989.  
  990.         ReleaseSemaphore(&dstpal->lock);
  991.     }
  992.     
  993.     return result;
  994. }
  995.  
  996.  
  997. /************************************************************************** 
  998. **
  999. **    convertchunky
  1000. */
  1001.  
  1002. LIBAPI ULONG ConvertChunkyA(UBYTE *src, RNDPAL *srcpal, UWORD w, UWORD h, UBYTE *dst, RNDPAL *dstpal, struct TagItem *tags)
  1003. {
  1004.     ULONG result = REND_NO_DATA;
  1005.  
  1006.     if (src && dst && w && h && dstpal)
  1007.     {
  1008.         struct RenderData data;
  1009.         memfill8((UBYTE *) &data, sizeof(struct RenderData), 0);
  1010.  
  1011.         ObtainSemaphore(&dstpal->lock);
  1012.         ObtainSemaphoreShared(&srcpal->lock);
  1013.  
  1014.         data.src = src;
  1015.         data.srcpal = srcpal;
  1016.         data.srcbpp = 1;
  1017.         data.dst = dst;
  1018.         data.dstpal = dstpal;
  1019.         data.width = w;        
  1020.         data.height = h;
  1021.         result = initrender(&data, tags);
  1022.         if (result == REND_SUCCESS)
  1023.         {
  1024.             result = (*data.renderyfunc)(&data);
  1025.         }
  1026.         exitrender(&data);
  1027.  
  1028.         ReleaseSemaphore(&srcpal->lock);
  1029.         ReleaseSemaphore(&dstpal->lock);
  1030.     }
  1031.     
  1032.     return result;
  1033. }
  1034.